<template>
	<div>
		<vue-advanced-chat
			height="calc(100vh - 50px)"
			:current-user-id="currentUserId"
			:rooms="JSON.stringify(rooms)"
			:rooms-loaded="true"
            :rooms-list-opened="false"
            :show-audio="true"
            :multiple-files="false"
			:messages="JSON.stringify(messages)"
			:messages-loaded="messagesLoaded"
			@send-message="sendMessage($event.detail[0])"
		>
    <!-- @fetch-messages="fetchMessages($event.detail[0])" -->
    </vue-advanced-chat>
	</div>
</template>

<script lang="ts">
export default {
    name: 'ChatRoom'
}
</script>

<script lang="ts" setup>
import { onMounted, onUnmounted, ref } from 'vue';
import { register } from 'vue-advanced-chat'
import { useRoute } from 'vue-router';
import { message } from 'ant-design-vue';
import store from './store'
import { sendMessageFiles, getRoomMessages, getRoomById, getMembers } from '@/api/room_api'

register()

const currentUserId = ref<string>('')
const rooms = ref<any[]>([])
const messages = ref<any[]>([])
const messagesLoaded = ref<boolean>(false)
const roomId = ref<number>(0)

let websocket: WebSocket | null = null; // 用于存储实例化后websocket
let rec: any; // 断线重连后，延迟5秒重新创建WebSocket连接  rec用来存储延迟请求的代码

// 创建websocket
function creatWebSocket(wsUrl: string) {
  console.log("websocket==================");
  // 判断当前浏览器是否支持WebSocket
  if ("WebSocket" in window) {
    console.log("当前浏览器支持 WebSocket");
  } else if ("MozWebSocket" in window) {
    console.log("当前浏览器支持 MozWebSocket");
  } else {
    message.error("当前浏览器不支持 WebSocket");
  }


  try {
    initWebSocket(wsUrl); // 初始化websocket连接
  } catch (e) {
    console.log("尝试创建连接失败");
    reConnect(wsUrl); // 如果无法连接上 webSocket 那么重新连接！可能会因为服务器重新部署，或者短暂断网等导致无法创建连接
  }
}

function initWebSocket(wsUrl: string) {
  websocket = new WebSocket(wsUrl);
  console.log("websocket:", websocket);


  websocket.onopen = function () {
    store.dispatch('connect');
  };


  //   // 接收
  websocket.onmessage = function (e: MessageEvent<any>) {
    console.log(e.data)
    const data = JSON.parse(e.data);
    messages.value.push(data)
  };


  // 连接发生错误
  websocket.onerror = function () {
    console.log("WebSocket连接发生错误");
    //     isConnect = false; // 连接断开修改标识
    reConnect(wsUrl); // 连接错误 需要重连
  };


  websocket.onclose = function (e) {
    store.dispatch('disconnect');
  };
}

let reConnect = (wsUrl: string) => {
  console.log("尝试重新连接");
  if (store.state.isConnected) return; // 如果已经连上就不在重连了
  rec && clearTimeout(rec);
  rec = setTimeout(function () {
    // 延迟5秒重连  避免过多次过频繁请求重连
    creatWebSocket(wsUrl);
  }, 5000);
};

onMounted(async () => {
    const router = useRoute()
    roomId.value = Number(router.params.id)
    await getRoomById(roomId.value)
    .then(resp => {
        rooms.value.push({
            roomId: roomId.value,
            roomName: resp.data.name,
            avatar: resp.data.coverUrl,
            users: []
        })
    })
    .catch(err => {});
    await getMembers(roomId.value)
    .then(resp=>{
        for (let i = 0; i < resp.data.length; i++) {
            rooms.value[0].users.push({
                _id: resp.data[i].value.uid,
                username: resp.data[i].label
            })
        }
        rooms.value[0].users.push({
                _id: "bot",
                username: "骰娘"
            })
    })
    .catch(err=>{});
    console.log(rooms)
    currentUserId.value = localStorage.getItem("uid")!
    const ip = `ws://127.0.0.1:8082/ws?roomId=${roomId.value}&uuid=${currentUserId.value}`
    store.dispatch(ip)
    creatWebSocket(ip)
    await addMessages()
});

onUnmounted(() => {
    if (websocket) {
        websocket.close();
        message.info("与房间的连接断开")
    }
})

const fetchMessages = (options:any) => {
    setTimeout(() => {
        if (options.reset) {
            addMessages(true)
        } else {
            addMessages()
            messagesLoaded.value = true
        }
    })
}

const addMessages = async(reset?:any) => {
    await getRoomMessages(roomId.value)
    .then(resp => {
      for (let i = resp.data.length-1; i >= 0; i--) {
        let msg = {
            _id: resp.data[i].id,
            content: resp.data[i].content,
            senderId: resp.data[i].senderId,
            username: resp.data[i].username,
            date: resp.data[i].date,
            timestamp: resp.data[i].timeStamp,
            avatar: resp.data[i].avatar,
            files: resp.data[i].files
        };
        messages.value.push(msg);
      }
    })
    .catch(err => {})
}

const sendMessage = async (message:any) => {
    console.log(message)
    let data = {
        _id: messages.value.length,
        content: message.content,
        username: localStorage.getItem("username"),
        senderId: currentUserId.value,
        timestamp: GetDate('HH:mm:ss'),
        date: GetDate('YYYY-MM-DD'),
        avatar: localStorage.getItem("avatar"),
        files: message.files,
        roomId: roomId.value,
    }  
    if (message.files != null && message.files.length != 0) {
        for (let i = 0, l = message.files.length; i < l; i++) {
          // 处理文件
          let formData = new FormData
          formData.append("roomId", String(roomId.value))
          formData.append("file", message.files[i].blob)
          await sendMessageFiles(formData)
          .then(resp => {
            data.files[i].url = resp.data.url
            data.files[i].path = resp.data.path
          })
          .catch(err => {})
        }
    }
    if (websocket && store.state.isConnected) { // 检查连接状态
        websocket.send(JSON.stringify(data)); 
    }
}

const GetDate = (M: string, Time: Date | null | string | number = null) => {
  let D: Date = Time ? new Date(Time) : new Date()
  let P: RegExp = /(Y{2,4}|M{1,2}|D{1,2}|H{1,2}|h{1,2}|m{1,2}|s{1,2}|C{1,2}|W{1,2})/g
  let ToZ: any = (S: string | number) => ((Number(S) < 10) ? '0' + S : S)
  let DS: string = M.replace(P, ($0: string) => {
    switch ($0) {
      case 'YY': return D.getFullYear().toString().slice(-2)
      case 'YYYY': return D.getFullYear()
      case 'M': return D.getMonth() + 1
      case 'MM': return ToZ(D.getMonth() + 1)
      case 'D': return D.getDate()
      case 'DD': return ToZ(D.getDate())
      case 'W': return D.getDay()
      case 'WW': return ['日', '一', '二', '三', '四', '五', '六'][D.getDay()]
      case 'H': return D.getHours()
      case 'HH': return ToZ(D.getHours())
      case 'm': return D.getMinutes()
      case 'mm': return ToZ(D.getMinutes())
      case 's': return D.getSeconds()
      case 'ss': return ToZ(D.getSeconds())
      case 'C': return Math.trunc(D.getTime() / 1000)
      case 'CC': return D.getTime()
      default: return $0
    }
  })
  return DS
}
</script>

<style lang="scss">
body {
	font-family: 'Quicksand', sans-serif;
}
</style>